# -*- coding: utf-8 -*-
# ----------------------------------------------------------------------------
# $Id: models.py 32 2009-08-01 19:46:18Z semente $
# ----------------------------------------------------------------------------
#
#  Copyright (c) 2008 Guilherme Mesquita Gondim
#
#  This file is part of django-fleshin.
#
#  django-fleshin is free software under terms of the GNU General
#  Public License version 3 (GPLv3) as published by the Free Software
#  Foundation. See the file README for copying conditions.
#

"""
Models definitions for Fleshin.
"""

import re, Image
from datetime import datetime
from os import path

from django.contrib.sites.managers import CurrentSiteManager
from django.contrib.sites.models import Site
from django.db import models
from django.db.models import permalink
from django.utils.translation import ugettext_lazy as _

from fleshin.managers import PublishedManager, CurrentSitePublishedManager
from fleshin.settings import HAS_TAG_SUPPORT

if HAS_TAG_SUPPORT:
    from tagging.fields import TagField

GET_THUMB_PATTERN = re.compile(r'^get_photo_(\d+)x(\d+)_(url|filename)$')

class Album(models.Model):
    name = models.CharField(_('name'), max_length=50, unique=True)
    slug = models.SlugField(
        _('slug'),
        unique=True,
        help_text=_('Automatically built from the name. A slug is a short '
                    'label generally used in URLs.'),
    )
    description = models.TextField(_('description'), blank=True)

    class Meta:
        verbose_name  = _('album')
        verbose_name_plural = _('albums')

    def __unicode__(self):
        return self.name

    @permalink
    def get_absolute_url(self):
        return ('fleshin-photo-album-list', None, {
            'album': str(self.slug),
        })

    def get_random_photo(self):
        queryset = self.photo_set.all()
        if queryset:
            return queryset.order_by('?')[0]
        return None

class Photo(models.Model):
    photo = models.ImageField(
        _('photo'),
        upload_to='photos/%Y/%m/%d',
        width_field='width',
        height_field='height',
    )
    width = models.SmallIntegerField(_('width'), editable=False)
    height = models.SmallIntegerField(_('height'), editable=False)
    caption = models.CharField(_('caption'), max_length=100)
    slug = models.SlugField(
        _('slug'),
        unique=True,
        help_text=_('Automatically built from the caption. A slug is a short '
                    'label generally used in URLs.'),
    )
    date = models.DateField(_('date'), blank=True, null=True)
    time = models.TimeField(_('time'), blank=True, null=True)
    place = models.CharField(_('place'), blank=True, max_length=70)
    photographer = models.CharField(
        _('photographer'),
        blank=True,
        max_length=50
    )
    description = models.TextField(_('description'), blank=True)
    pub_date = models.DateTimeField(
        _('date published'),
        default=datetime.now,
        help_text=_('Photos in future dates are only published on '
                    'correct date.'),
    )
    is_published = models.BooleanField(_('published'), default=True)
    publish_on = models.ManyToManyField(
        Site,
        verbose_name=_('publish on'),
    )
    enable_comments = models.BooleanField(_('enable comments'), default=True)
    album = models.ForeignKey(Album, verbose_name=_('album'))

    if HAS_TAG_SUPPORT:
        tags = TagField(blank=True)

    # managers
    objects   = models.Manager()
    published = PublishedManager()
    on_site   = CurrentSiteManager('publish_on')
    published_on_site = CurrentSitePublishedManager('publish_on')

    class Meta:
        get_latest_by = 'pub_date'
        ordering      = ('-pub_date',)
        verbose_name  = _('photo')
        verbose_name_plural = _('photos')

    def __unicode__(self):
        return self.caption

    def __getattr__(self, name):
        """
        Deploys dynamic methods for on-demand thumbnails creation with any
        size.

        Syntax::

            get_photo_[WIDTH]x[HEIGHT]_[METHOD]

        Where *WIDTH* and *HEIGHT* are the pixels of the new thumbnail and
        *METHOD* can be ``url`` or ``filename``.

        Example usage::

            >>> photo = Photo(photo="/tmp/example.jpg", ...)
            >>> photo.save()
            >>> photo.get_photo_320x240_url()
            u"http://media.example.net/photos/2008/02/26/example_320x240.jpg"
            >>> photo.get_photo_320x240_filename()
            u"/srv/media/photos/2008/02/26/example_320x240.jpg"
        """
        match = re.match(GET_THUMB_PATTERN, name)
        if match is None:
            raise AttributeError, name
        width, height, method = match.groups()
        size = int(width), int(height)

        def get_photo_thumbnail_filename():
            file, ext = path.splitext(self.photo.file.name)
            return file + '_%sx%s' % size + ext

        def get_photo_thumbnail_url():
            url, ext = path.splitext(self.photo.url)
            return url + '_%sx%s' % size + ext

        thumbnail = get_photo_thumbnail_filename()
        if not path.exists(thumbnail):
            img = Image.open(self.photo.file.name)
            img.thumbnail(size, Image.ANTIALIAS)
            img.save(thumbnail)
        if method == "url":
            return get_photo_thumbnail_url
        else:
            return get_photo_thumbnail_filename

    @permalink
    def get_absolute_url(self):
        return ('fleshin-photo', None, {
            'album': str(self.album.slug),
            'slug' : str(self.slug),
        })

    def in_future(self):
        return self.pub_date > datetime.now()


# signals
from django.db.models import signals

def photo_pre_save(sender, instance, signal, *args, **kwargs):
    try:
        # update instance's pub_date if photo was not published
        e = Photo.objects.get(id=instance.id)
        if not e.is_published:
            instance.pub_date = datetime.now()
    except Photo.DoesNotExist:
        pass

signals.pre_save.connect(photo_pre_save, sender=Photo)
